package android.matrix;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * La clase <code>FileMatrix</code> extiende de la clase abstracta 
 * <code>AbstractMatrix</code> y posee dos constructores. Uno que crea una 
 * instancia a partir de un objeto tipo <code>MatrixStub</code>, la cual es una
 * clase envoltorio para subclases de <code>AbstracMatrix</code>.
 *  
 * @author Rafael Asprilla
 *
 */
public class FileMatrix extends AbstractMatrix{
	
	/**
	 * Constructor de la clase <code>FileMatrix</code>. Crea una instancia de 
	 * la clase y un archivo .mat que permite realizar operaciones de matrices 
	 * remotas.
	 * 
	 * @param matrix
	 * Envoltorio de los datos en la matriz.
	 * @throws IOException
	 * Tira una excepción si hay un problema con el archivo.
	 */
	public FileMatrix(MatrixStub matrix) throws IOException{
		
		super(matrix.element);
		
		this.filename = matrix.filename;
		File matfile = new File("/home/drakoniss/tesis/"+this.filename);
		DataOutputStream out = new DataOutputStream(new FileOutputStream(matfile));
		out.writeInt(Integer.reverseBytes(rows));
		out.writeInt(Integer.reverseBytes(columns));
		out.writeByte('\n');		
		for(int i = 0; i < rows; i++)
		{
			for(int j = 0; j < columns; j++)
			{
				out.writeInt(Integer.reverseBytes(Float.floatToRawIntBits(element[i][j])));
			}
			out.writeByte('\n');
		}
		out.close();
	}
	
	/**
	 * Constructor de la clase <code>FileMatrix</code>. Crea una instancia de 
	 * la clase a partir de un archivo .mat.
	 * 
	 * @param filename
	 * Nombre de archivo .mat que contiene los datos.
	 * @throws IOException
	 * Tira una excepción si hay un problema con el archivo.
	 */
	public FileMatrix(String filename) throws IOException{
		
		super();
		
		this.filename = filename;
		File file = new File("/home/drakoniss/tesis/"+this.filename);
		if(!file.exists()){
			throw new FileNotFoundException();	
		}else{
			DataInputStream data = new DataInputStream(new FileInputStream(file)); 
			this.rows = Integer.reverseBytes(data.readInt());
			this.columns = Integer.reverseBytes(data.readInt());
			data.skip(1);
			element = new float[this.rows][this.columns];
			for(int i = 0; i < rows; i++){
				for(int j = 0; j < columns; j++)
					this.element[i][j] = Float.intBitsToFloat(Integer.reverseBytes(data.readInt()));
				data.skip(1);
			}
			data.close();
		}
	}

	/**
	 * Crea un envoltorio de matrices utilizando una instancia de 
	 * <code>MatrixStub</code>.
	 * 
	 * @return
	 * Retorna el envoltorio de los datos de la matriz.
	 */
	public MatrixStub getStub(){
		return new MatrixStub(this.element, this.filename);
	}
}
